/**
 * @file
 * @author dousha
 * @date 2020-12-31
 */
#ifndef LIBMULTIWII_MWC_PROTOCOL_H
#define LIBMULTIWII_MWC_PROTOCOL_H

#include <stdint.h>

#define MWP_FRAME_BUFFER_LENGTH 8
#define MWP_FRAME_DATA_MAX_LENGTH 256
/**
 * @brief Use dynamic memory allocation.
 *
 * 0 = No
 * 1 = Yes
 */
#define MWP_DYNAMIC_ALLOCATION 0
/**
 * @brief Function to call for memory allocation.
 * The first argument must be the byte size to be allocated.
 * The function must return NULL or a equivalent value specified by
 * `MWP_NULL`.
 */
#define MWP_MALLOC malloc
/**
 * @brief Function to call for memory deallocation.
 * The first argument must be the pointer to the allocated memory.
 */
#define MWP_FREE free
#define MWP_NULL NULL

typedef enum {
	STATE_INVALID = 0,
	STATE_PREAMBLE_DOLLAR = 1,
	STATE_PREAMBLE_M = 2,
	STATE_PREAMBLE_DIRECTION = 3,
	STATE_DATA_LENGTH = 4,
	STATE_COMMAND = 5,
	STATE_DATA = 6,
	STATE_CHECKSUM = 7,
} MWPState;

typedef struct {
	uint8_t direction;
	uint8_t command;
	uint8_t length;
#if MWP_DYNAMIC_ALLOCATION == 1
	uint8_t *data;
#else
	uint8_t data[MWP_FRAME_DATA_MAX_LENGTH];
#endif
} MWPFrame;

typedef void (*FrameCallbackFunction)(const MWPFrame *);

extern void mwp_init(FrameCallbackFunction);

extern void mwp_finalize();

extern void mwp_advance(uint8_t);

#endif	// LIBMULTIWII_MWC_PROTOCOL_H
